package weaver.ofs.interfaces;


import org.apache.commons.lang3.StringUtils;
import weaver.file.Prop;
import weaver.workflow.request.todo.DataObj;

import javax.annotation.PreDestroy;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class SendRequestStatusDataProxy implements SendRequestStatusDataInterfaces{

    private static final Logger log = LoggerFactory.getLogger(SendRequestStatusDataProxy.class);

    // 持有最新的实现类实例（由HotSwapClassLoader更新）
    private static volatile OaPushMessageInterface realImpl;

    // ============================== 从配置文件注入参数 ==============================

    private static String baseClassPath;


    private static String basePackage;


    private static String excludedClassesStr;


    private static int maxClassLoaders;


    // ============================== 核心变量 ==============================
    // 记录每个类的最后修改时间（线程安全）
    private final static Map<String, Long> classLastModifiedMap = new ConcurrentHashMap<>();
    // 保存类加载器引用（弱引用，便于回收）
    private final static List<WeakReference<ClassLoader>> classLoaders = new ArrayList<>();
    // 当前使用的类加载器（volatile保证可见性）
    private static volatile ClassLoader currentClassLoader;
    // 排除的类列表（初始化时解析）
    private static List<String> excludedClasses;




    /**
     * 后台设置id
     */
    public String id;
    /**
     * 设置的系统编号
     */
    public String syscode;
    /**
     * 服务器URL
     */
    public String serverurl;
    /**
     * 流程白名单
     */
    public ArrayList<String> workflowwhitelist;
    /**
     * 人员白名单
     */
    public ArrayList<String> userwhitelist;


    public String getId() {
        return id;
    }

    public String getSyscode() {
        return syscode;
    }

    public String getServerurl() {
        return serverurl;
    }

    public ArrayList<String> getWorkflowwhitelist() {
        return workflowwhitelist;
    }

    public ArrayList<String> getUserwhitelist() {
        return userwhitelist;
    }


    /**
     * 实现消息推送的具体方法
     *
     * @param datas 传入的请求数据对象数据集
     */
    public synchronized void SendRequestStatusData(ArrayList<DataObj> datas) {
        log.info("Ecology统一待办数据推送金盛兰云台：start");
        log.info("datas的尺寸大小："+datas.size());
        if (realImpl == null) {
            log.info("初始化实现类...");
            init();
        }
        realImpl.SendRequestStatusData(datas);
        log.info("Ecology统一待办数据推送金盛兰云台：end");
    }


    static {
        init();
    }


    public static void init() {
        try {
            baseClassPath = Prop.getPropValue("JslWorkflow", "hotswap_classPath");
            if (StringUtils.isEmpty(baseClassPath)){
                baseClassPath = "d:/";
            }
            basePackage = Prop.getPropValue("JslWorkflow", "hotswap_message_basePackage");
            if (StringUtils.isEmpty(basePackage)){
                basePackage = "hotswap.message";
            }
            excludedClassesStr = Prop.getPropValue("JslWorkflow", "hotswap_excludedClassesStr");
            maxClassLoaders = Integer.parseInt(Prop.getPropValue("JslWorkflow", "hotswap_maxClassLoaders"));
            if (maxClassLoaders == 0){
                maxClassLoaders = 3;
            }

            // 1. 解析排除的类列表（逗号分隔转List）
            excludedClasses = parseExcludedClasses();
            log.info("热更新排除的类：{}", excludedClasses);

            // 2. 扫描可热更新的类
            List<String> classNames = scanPackage(basePackage, baseClassPath);
            if (classNames.isEmpty()) {
                log.error("未找到可热更新的类（路径：{}，包名：{}）", baseClassPath, basePackage);
            }else {
                log.info("发现可热更新的类：{}", classNames);

                // 3. 初始化类修改时间记录
                log.info("初始化类修改时间记录...");
                initClassLastModified(classNames);
                log.info("类修改时间记录初始化完成");

                // 4. 初始化类加载器并加载初始类
                log.info("初始化类加载器...");
                initClassLoader();
                log.info("类加载器初始化完成");
                int successCount = loadAllClasses(classNames);
                log.info("初始加载完成：共{}个类，成功加载{}个", classNames.size(), successCount);
            }
        } catch (Exception e) {
            log.error("热更新服务初始化失败", e);
            throw new RuntimeException("热更新服务初始化异常", e);
        }
    }

    /**
     * 手动触发热更新（供Controller调用）
     * @return 更新结果（成功的类列表、失败的类列表）
     */
    public Map<String, List<String>> triggerHotSwap() {
        // 结果封装：success-成功列表，fail-失败列表
        Map<String, List<String>> result = new ConcurrentHashMap<>();
        List<String> infoList = new ArrayList<>();

        try {
            log.info("开始执行热更新检查...");

            // 1. 重新扫描最新的类列表（支持新增类）
            List<String> classNames = scanPackage(basePackage, baseClassPath);
            if (classNames.isEmpty()) {
                infoList.add("未找到可热更新的类");
                result.put("info", infoList);
                return result;
            }

            // 2. 检查变化的类
            List<String> changedClasses = checkChangedClasses(classNames);
            if (changedClasses.isEmpty()) {
                infoList.add("未检测到任何类变化，无需更新");
                result.put("info", infoList);
                return result;
            }
            log.info("检测到变化的类：{}", changedClasses);

            // 3. 同步创建新类加载器并重新加载
            synchronized (this) {
                initClassLoader(); // 新建类加载器（避免与旧类冲突）
                // 单个文件变更后，需要重新加载所有类
                int successCount = loadAllClasses(classNames);

                log.info("变更后重新加载模块完成：共{}个类，成功加载{}个", classNames.size(), successCount);
                infoList.add("变更后重新加载模块完成：共"+classNames.size()+"个类，成功加载"+successCount+"个");
                // 清理旧的类加载器，防止元空间泄漏
                cleanupClassLoaders();
            }
        } catch (Exception e) {
            log.error("热更新执行异常", e);
            infoList.add("热更新流程异常：" + e.getMessage());
        }

        result.put("info", infoList);
        return result;
    }

    /**
     * 解析排除的类列表（从配置文件的字符串转List）
     */
    private static List<String> parseExcludedClasses() {
        if (excludedClassesStr == null || excludedClassesStr.trim().isEmpty()) {
            return Collections.emptyList(); // 或 Collections.emptyList()
        }
        return Arrays.stream(excludedClassesStr.split(","))
                .map(String::trim)
                .filter(cls -> !cls.isEmpty())
                .collect(Collectors.toList());
    }


    /**
     * 扫描指定包下的所有类（排除接口等不需要热更的类）
     */
    private static List<String> scanPackage(String packageName, String baseClassPath) {
        log.info("开始扫描包：{}", baseClassPath + packageName);
        List<String> classNames = new ArrayList<>();
        String packagePath = packageName.replace('.', File.separatorChar);

        // 检查类文件根目录是否存在
        File baseDir = new File(baseClassPath);
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            log.error("类文件根目录不存在或不是目录：{}", baseClassPath);
            return classNames;
        }

        // 扫描包对应的目录
        File packageDir = new File(baseClassPath + packagePath);
        if (packageDir.exists() && packageDir.isDirectory()) {
            findClasses(packageDir, packageName, classNames);
        } else {
            log.error("包目录不存在：{}", packageDir.getAbsolutePath());
        }

        // 排除不需要热更新的类
        classNames.removeAll(excludedClasses);
        return classNames;
    }


    /**
     * 递归查找目录下的所有.class文件
     */
    private static void findClasses(File dir, String packageName, List<String> classNames) {
        if (!dir.exists()) {
            return;
        }

        File[] files = dir.listFiles();
        if (files == null) {
            return;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                // 递归处理子目录（包名拼接子目录名）
                findClasses(file, packageName + "." + file.getName(), classNames);
            } else if (file.getName().endsWith(".class")) {
                // 处理.class文件：包名 + 类名（去掉.class后缀）
                String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                classNames.add(className);
            }
        }
    }


    /**
     * 初始化类的最后修改时间
     */
    private static void initClassLastModified(List<String> classNames) {
        for (String className : classNames) {
            File classFile = getClassFile(className);
            if (classFile.exists()) {
                classLastModifiedMap.put(className, classFile.lastModified());
                log.info("初始化类[{}]的最后修改时间：{}", className, classFile.lastModified());
            }
        }
    }


    /**
     * 初始化类加载器（新建HotSwapClassLoader）
     */
    private static void initClassLoader() {
        currentClassLoader = new SendMessageClassLoader(baseClassPath);
        synchronized (classLoaders) {
            log.info("新建类加载器（ID：{}），当前加载器总数：{}", currentClassLoader.hashCode(), classLoaders.size());
            // 先清理已被GC回收的弱引用
            classLoaders.removeIf(ref -> ref.get() == null);
            // 添加新的类加载器（弱引用）
            classLoaders.add(new WeakReference<>(currentClassLoader));
            log.info("新建类加载器（ID：{}），当前加载器总数：{}", currentClassLoader.hashCode(), classLoaders.size());
        }
    }


    /**
     * 加载所有类（返回成功数量）
     */
    private static int loadAllClasses(List<String> classNames) {
        int successCount = 0;
        log.info("开始加载所有类");
        log.info("classNames：{}", classNames);
        for (String className : classNames) {
            if (loadSingleClass(className)) {
                successCount++;
            }
        }
        log.info("加载所有类完成：成功{}个，失败{}个", successCount, classNames.size() - successCount);
        return successCount;
    }


    /**
     * 加载单个类（返回是否成功）
     */
    private static boolean loadSingleClass(String className) {
        try {
            log.info("开始加载类[{}]", className);
            log.info("类[{}]加载器：{},加载器ID：{}", className, currentClassLoader,currentClassLoader.hashCode());
            // 核心：通过当前类加载器加载类
            Class<?> aClass = currentClassLoader.loadClass(className);
            log.info("类[{}]加载成功（加载器ID：{}）", className, currentClassLoader.hashCode());
            // 若发现OaPushMessageInterface接口，则切换实现
            Class<?> interfaceClass = OaPushMessageInterface.class;
            if (!aClass.isInterface() && interfaceClass.isAssignableFrom(aClass)){
                // 安全切换（因为接口是同一个类加载器加载的）
                realImpl = (OaPushMessageInterface) aClass.newInstance();
            }

            return true;

        } catch (Exception e) {
            log.error("类[{}]加载失败", className, e);
            return false;
        }
    }


    /**
     * 测试调用类的方法（如sayHello）
     */
    private void invokeTestMethod(Class<?> clazz, String methodName) throws Exception {
        // 实例化（要求类有默认无参构造器）
        Object instance = clazz.getDeclaredConstructor().newInstance();
        // 获取方法并调用
        Method method = clazz.getMethod(methodName);
        method.invoke(instance);
        log.info("调用类[{}]的方法[{}]成功", clazz.getName(), methodName);
    }

    /**
     * 检查变化的类（对比最后修改时间）
     */
    private List<String> checkChangedClasses(List<String> classNames) {
        List<String> changedClasses = new ArrayList<>();
        for (String className : classNames) {
            File classFile = getClassFile(className);
            if (classFile.exists()) {
                long currentModified = classFile.lastModified();
                long lastModified = classLastModifiedMap.getOrDefault(className, 0L);

                // 对比修改时间：不同则认为类已变化
                if (currentModified != lastModified) {
                    changedClasses.add(className);
                    // 更新最后修改时间（下次对比用）
                    classLastModifiedMap.put(className, currentModified);
                    log.info("类[{}]已变化（旧时间：{}，新时间：{}）", className, lastModified, currentModified);
                }
            } else {
                log.warn("类[{}]的文件不存在：{}", className, classFile.getAbsolutePath());
            }
        }
        return changedClasses;
    }


    /**
     * 清理旧的类加载器（保留最新的maxClassLoaders个）
     */
    private void cleanupClassLoaders() {
        synchronized (classLoaders) {
            // 先移除已被GC回收的弱引用
            classLoaders.removeIf(ref -> ref.get() == null);
            int currentSize = classLoaders.size();

            // 如果超过最大数量，移除旧的加载器（保留最新的maxClassLoaders个）
            if (currentSize > maxClassLoaders) {
                int removeCount = currentSize - maxClassLoaders;
                classLoaders.subList(0, removeCount).clear();
                log.info("清理旧类加载器：移除{}个，剩余{}个", removeCount, classLoaders.size());
            }
        }
    }


    /**
     * 获取类对应的文件对象
     */
    private static File getClassFile(String className) {
        String classFilePath = className.replace('.', File.separatorChar) + ".class";
        log.info("类[{}]对应的文件路径：{}", className, baseClassPath  + classFilePath);
        return new File(baseClassPath +   classFilePath);
    }


    /**
     * Spring销毁回调：服务关闭时清理资源
     */
    @PreDestroy
    public void destroy() {
        log.info("热更新服务开始清理资源...");
        // 清理类加载器和修改时间记录
        synchronized (classLoaders) {
            classLoaders.clear();
        }
        classLastModifiedMap.clear();
        log.info("热更新服务资源清理完成");
    }

}
